#ifndef ARGSFILEPARSER_H
#define ARGSFILEPARSER_H

#include "rapidxml.hpp"

#include <string>
#include <vector>
#include <map>

using namespace rapidxml;


class ArgsFileEntry;
class ArgsFileValueEntry;
class ArgsFileGroupEntry;
class ArgsFile;

typedef enum {intValue, floatValue, doubleValue, stringValue} ArgsFileValueType;

typedef std::map<std::string, std::string> ArgsFileExtraAttrs;


class ArgsFileEntry
{
public:
    ArgsFileEntry(void);

    virtual ~ArgsFileEntry(void);

    virtual bool isValue(void) = 0;

    virtual bool isGroup(void) = 0;


public:
    std::string name;
    std::string type;
    std::string help;
    std::vector<ArgsFileValueEntry> hintDict;
    ArgsFileExtraAttrs extraAttrs;
} ;


class ArgsFileValueEntry : public ArgsFileEntry
{
public:
    ArgsFileValueEntry(void);

    virtual ~ArgsFileValueEntry(void);

    bool isValue(void) { return true;}

    bool isGroup(void) { return false;}

public:
    std::string value;
    ArgsFileValueType valueType;
    std::string defaultValue;
    int valueSize;
    int valueTupleSize;
    std::string widget;
};


class ArgsFileGroupEntry : public ArgsFileEntry
{
public:
    ArgsFileGroupEntry(void);

    virtual ~ArgsFileGroupEntry(void);

    bool isValue(void) { return false;}

    bool isGroup(void) { return true;}

public:
    bool closed;
    std::vector<ArgsFileEntry *> children;
};


class ArgsFile : public ArgsFileGroupEntry
{
public:
    ArgsFile(void);

    virtual ~ArgsFile(void);

    static ArgsFile *parse(std::string filePath);

private:
    static ArgsFile *parseXML(char *buffer, std::string filePath);

    static ArgsFile *parseRootNode(xml_node<>* rootNode);

    static ArgsFileEntry *parseEntry(xml_node<>* parentNode);

    static ArgsFileGroupEntry *parseGroup( xml_node<>* parentNode,
                                           ArgsFileExtraAttrs &extraAttrs);

    static ArgsFileValueEntry *parseParam(xml_node<>* node,
                                          ArgsFileExtraAttrs &extraAttrs);

    static std::string extractExtraAttr( ArgsFileExtraAttrs &extraAttrs,
                                         std::string attrName);

    static void error(std::string msg);

public:
    std::string filePath;
    std::string format;
};


#endif // ARGSFILEPARSER_H
